package utils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"tools-api/src/common/def"
)

// pkcs7Padding 填充数据
func pkcs7Padding(ciphertext []byte) []byte {
	bs := aes.BlockSize
	padding := bs - len(ciphertext)%bs
	paddingText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, paddingText...)
}

// pkcs7UnPadding 放出数据
func pkcs7UnPadding(origData []byte) []byte {
	length := len(origData)
	unPadding := int(origData[length-1])
	unPadding = length - unPadding
	if unPadding < 0 {
		unPadding = 0
	}
	return origData[:(unPadding)]
}

// AesEncrypt 加密
// origData 原始数据
// key 密码
// iv 偏移量
func AesEncrypt(origData, key, iv string) (string, error) {
	block, err := aes.NewCipher([]byte(key))
	if err != nil {
		return "", err
	}

	newOrigData := []byte(origData)
	newOrigData = pkcs7Padding(newOrigData)
	blockMode := cipher.NewCBCEncrypter(block, []byte(iv))
	crypted := make([]byte, len(newOrigData))
	blockMode.CryptBlocks(crypted, newOrigData)
	return base64.StdEncoding.EncodeToString(crypted), nil
}

// AesDecrypt 解密
// crypted 加密值
// key 密码
// iv 偏移量
func AesDecrypt(crypted, key, iv string) (string, error) {

	block, err := aes.NewCipher([]byte(key))
	if err != nil {
		return "", err
	}

	newCrypted, err := base64.StdEncoding.DecodeString(crypted)
	if err != nil {
		return "", err
	}
	blockMode := cipher.NewCBCDecrypter(block, []byte(iv))
	origData := make([]byte, len(newCrypted))
	blockMode.CryptBlocks(origData, newCrypted)
	origData = pkcs7UnPadding(origData)
	return string(origData), nil
}

func getDefSecret() (string, string) {
	key := def.Config.GetString("secret.def.key") // 解密也走新的
	iv := def.Config.GetString("secret.def.iv")
	return key, iv
}

// Encrypt 默认加密
func Encrypt(value string) string {
	if value == "" {
		return value
	}
	key, iv := getDefSecret()
	value, _ = AesEncrypt(value, key, iv)
	return value
}

// Decrypt 手机号解密
func Decrypt(value string) string {
	if value == "" {
		return ""
	}
	key, iv := getDefSecret()
	value, _ = AesDecrypt(value, key, iv)
	return value
}

// Md5String md5加密
func Md5String(str string) string {
	h := md5.New()
	//h.Write(helpers.StringToBytes(str))
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}

// HmacSha256 使用HMAC-SHA256算法生成签名
func HmacSha256(key, value string) string {
	h := hmac.New(sha256.New, []byte(key))
	h.Write([]byte(value))
	return hex.EncodeToString(h.Sum(nil))
}
